﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using IQReportes.Utils;
using System.Data;
using System.Data.SqlClient;
using System.Globalization;

namespace IQReportes.Models
{
    
    public class LogicaTransaccion
    {
        private TransaccionDAO dbTransaccion = new TransaccionDAO();
        private TreeTransaccionDAO dbTreeTransacciones = new TreeTransaccionDAO();
        private ConsolidadoEstadoTxnDAO dbConsolidadoEstados = new ConsolidadoEstadoTxnDAO();
        private ConsolidadoMontoTxnDAO dbConsolidadoMontos = new ConsolidadoMontoTxnDAO();
        private ConsolidadoTipoTxnDAO dbConsolidadoTipos = new ConsolidadoTipoTxnDAO();
        private DirDAO dbDirs = new DirDAO();

        private ConexionSQL dbSQL = new ConexionSQL();
        private SimuladorBD dbSimulador;
        private LogicaGeneral logicaGeneral = new LogicaGeneral();
        private Dictionary<int, string> diccionarioCategorias = new Dictionary<int, string>();
        private Dictionary<int, string> diccionarioTipos = new Dictionary<int, string>();
        private Dictionary<int, string> diccionarioEstados = new Dictionary<int, string>();
        private Dictionary<string, int> diccionarioDirsXLocal = new Dictionary<string, int>();
        private Dictionary<string, string> diccionarioLocalXCodigo = new Dictionary<string, string>();
        private Dictionary<string, string> diccionarioDistritos = new Dictionary<string, string>();
        private Dictionary<string, List<string>> diccionarioLocalesXDistrito = new Dictionary<string, List<string>>();
        private Dictionary<string, int> diccionarioTxnsExitosasXLocal = new Dictionary<string, int>();
        private Dictionary<string, int> diccionarioTxnsTotalesXLocal = new Dictionary<string, int>();

        private EstadoTransaccionDAO dbEstadoTxn = new EstadoTransaccionDAO();
        private TipoTransaccionDAO dbTiposTxn = new TipoTransaccionDAO();
        private CategoriaTransaccionDAO dbCategoriaTxn = new CategoriaTransaccionDAO();
        

        private List<Ubigeo> listaUbigeo = new List<Ubigeo>(); //dato inicial

        private void cargarDatosIniciales()
        {
            var listaTiposTxn = dbTiposTxn.tiposTransaccion;
            var listaEstadosTxn = dbEstadoTxn.estados;
            var listaCategoriasTxn = dbCategoriaTxn.categoriasTransaccion;
            

            foreach (var t in listaTiposTxn)
            {
                diccionarioTipos.Add(t.idTipo,t.vcNombre);
            }

            foreach (var e in listaEstadosTxn)
            {
                diccionarioEstados.Add(e.idEstado, e.vcNombre);
            }

            foreach (var c in listaCategoriasTxn)
            {
                diccionarioCategorias.Add(c.idCategoria, c.vcNombre);
            }
        }

        public LogicaTransaccion()
        {
            cargarDatosIniciales();
            //dbSimulador = new SimuladorBD();
            //dbSimulador.cargaDatosIniciales();
        }

        public List<TreeTransaccion> obtenerConsolidadoTransacciones(int unidadesAntiguedad, int codigoTabla, int institucion)
        {
            List<ConsolidadoGeneral> consolidado = new List<ConsolidadoGeneral>();
            List<TreeTransaccion> treeTransaccion = new List<TreeTransaccion>();
            List<TreeTransaccion> auxiliarTree = new List<TreeTransaccion>();
            treeTransaccion = armarTreeTransacciones(unidadesAntiguedad, codigoTabla,institucion);
            
            //OJOOOOOOOOOOO!!
            //treeTransaccion = dbSimulador.obtenerConsTreeSimulacionDB(1);
            /*foreach (TreeTransaccion elemento in treeTransaccion)
            {
                consolidado.Add(elemento);
            }
            return consolidado;*/
            return treeTransaccion;
        }

        private void obtenerDataSetTxnsXLocal(DataSet ds,int exitosas)
        {
            string codLocal;
            int cantTxns;
            foreach (DataRow dr in ds.Tables[0].Rows)
            {
                codLocal = dr[0].ToString();
                cantTxns = Int32.Parse(dr[1].ToString());
                if (exitosas == Constantes.COD_TRANSACCIONES_EXITOSAS)
                {
                    diccionarioTxnsExitosasXLocal.Add(codLocal, cantTxns);
                }
                else
                {
                    diccionarioTxnsTotalesXLocal.Add(codLocal, cantTxns);
                }
            }
        }

        private void cargarTransaccionesXlocal(int unidadesAntiguedad, int codUnidadMedida,int institucion, int exitosas)
        {
            List<SqlParameter> listaParametros = new List<SqlParameter>();
            DataSet ds = new DataSet();
            
            SqlParameter param1 = new SqlParameter("@unidadesAntiguedad", SqlDbType.Int);
            SqlParameter param2 = new SqlParameter("@codUnidadMedida", SqlDbType.Int);
            SqlParameter param3 = new SqlParameter("@codInstitucion", SqlDbType.Int);
            SqlParameter param4 = new SqlParameter("@codEstadoTxn", SqlDbType.Int);

            param1.Value = unidadesAntiguedad;
            param2.Value = codUnidadMedida;
            param3.Value = institucion;
            param4.Value = exitosas;

            listaParametros.Add(param1);
            listaParametros.Add(param2);
            listaParametros.Add(param3);
            listaParametros.Add(param4);

            dbSQL.ejecutarSelectProcedureDS(Utils.ProcedimientosAlmacenados.transaccionesXLocal, listaParametros, ds);
            obtenerDataSetTxnsXLocal(ds,exitosas);
        }

        private void cargarDiccionariosTree()
        {
            listaUbigeo = dbDirs.ubigeos.ToList();
            logicaGeneral.cargarDiccionariosTree(diccionarioDirsXLocal, diccionarioLocalXCodigo,
                                            diccionarioLocalesXDistrito, listaUbigeo, diccionarioDistritos);
            //try
            //{
            //    //para obtener los numeros de dir por local
            //    var listaDirXLocal = dbDirs.dirs.GroupBy(a =>
            //        new
            //        {
            //            a.vcCodLocal
            //        }).Select(a => new
            //        {
            //            codLocal = a.Key.vcCodLocal,
            //            numDirs = a.Select(x => x.vcCodDIR).Distinct().Count()
            //        });

            //    foreach (var item in listaDirXLocal)
            //    {
            //        diccionarioDirsXLocal.Add(item.codLocal, item.numDirs);
            //    }

            //    //para obtener los nombre de locales unicos
            //    var listaLocalXCodigo = dbDirs.dirs.GroupBy(a =>
            //        new
            //        {
            //            a.vcCodLocal,
            //            a.vcLocal
            //        }).Select(a => new
            //        {
            //            codLocal = a.Key.vcCodLocal,
            //            nombreLocal = a.Key.vcLocal
            //        });
            //    //
            //    string espacios;
            //    foreach (var loc in listaLocalXCodigo)
            //    {
            //        espacios = Constantes.CADENA_VACIA;
            //        while (true)
            //        {
            //            if (diccionarioLocalXCodigo.ContainsValue(loc.nombreLocal))
            //            {
            //                espacios = espacios + " ";
            //            }
            //            else
            //            {
            //                diccionarioLocalXCodigo.Add(loc.codLocal, loc.nombreLocal + espacios);
            //                break;
            //            }
            //        }
            //    }

            //    //para obtener los locales por distrito
            //    var listaLocalXdistrito = dbDirs.dirs.GroupBy(a =>
            //        new
            //        {
            //            a.vcCodLocal,
            //            a.vcCodDistrito
            //        }).Select(a => new
            //        {
            //            codLocal = a.Key.vcCodLocal,
            //            codDistrito = a.Key.vcCodDistrito
            //        }).OrderBy(a=>a.codDistrito);

            //    List<string> listaLocales;
                
            //    foreach (var item in listaLocalXdistrito)
            //    {
            //        if (!diccionarioLocalesXDistrito.ContainsKey(item.codDistrito))
            //        {
            //            listaLocales = new List<string>();
            //            listaLocales.Add(item.codLocal);
            //            diccionarioLocalesXDistrito.Add(item.codDistrito, listaLocales);
            //        }
            //        else
            //        {
            //            diccionarioLocalesXDistrito[item.codDistrito].Add(item.codLocal);
            //        }
            //    }

            //    //para obtener los nombres de distrito unicos
            
            //string espacios;
            //listaUbigeo = dbDirs.ubigeos.ToList();

            //foreach (Ubigeo u in listaUbigeo)
            //{
            //    espacios = Constantes.CADENA_VACIA;
            //    while (true)
            //    {
            //        if (diccionarioDistritos.ContainsValue(u.vcDistrito + espacios))
            //        {
            //            espacios = espacios + " ";
            //        }
            //        else
            //        {
            //            diccionarioDistritos.Add(u.vcCodDistrito, u.vcDistrito + espacios);
            //            break;
            //        }
            //    }
            //}

            //    //departamentos
                
            //}
            //catch (Exception e)
            //{
            //    string gg = e.Message;
            //}

        }

        public void obtenerDepartamentos(List<String> departamentos)
        {
            try
            {
                var dptos = listaUbigeo.AsEnumerable().GroupBy(a => a.vcDepartamento).Select(k => new { Departamento = k.Key }).ToList();
                for (int i = 0; i < dptos.Count(); i++)
                {
                    departamentos.Add(dptos[i].Departamento);
                }
            }
            catch (Exception e)
            {
                string gg = e.Message;
            }
        }

        public List<String> obtenerProvinciasXDepartamento(string nombreDepartamento, List<String> provincias)
        {
            List<String> retorno = new List<String>();
            retorno = logicaGeneral.obtenerProvinciasXDepartamento(nombreDepartamento, provincias, listaUbigeo);
                        
            return retorno;
            
        }

        public List<String> obtenerDistritosXProvincia(string departamento, string provincia, List<String> distritos)
        {
            List<String> retorno = new List<String>();
            retorno = logicaGeneral.obtenerDistritosXProvincia(departamento, provincia, distritos, listaUbigeo,
                                                               diccionarioDistritos);
            return retorno;
        }

        public List<String> obtenerLocalesXdistrito(List<String> listaLocales, string codDistrito)
        {
            List<String> retorno = new List<String>();
            retorno = logicaGeneral.obtenerLocalesXdistrito(listaLocales, codDistrito, diccionarioLocalesXDistrito, 
                                                            diccionarioLocalXCodigo);
            
            return retorno;
            
        }


        private List<TreeTransaccion> armarTreeTransacciones(int unidadesAntiguedad, int codUnidadMedida, int institucion)
        {
            List<String> departamentos = new List<String>();//dato inicial
            List<TreeTransaccion> tree = new List<TreeTransaccion>();
            List<String> locales = new List<String>();
            List<String> auxDistritos = new List<String>();
            List<String> auxProvincias = new List<String>();
            List<String> auxDepartamentos = new List<String>();
            List<String> auxDistritos1 = new List<String>();
            List<String> auxProvincias1 = new List<String>();
            List<String> auxDepartamentos1 = new List<String>();
            List<String> auxLocales1 = new List<String>();
            string distritoactual;
            bool antes, despues;
            try
            {
                cargarDiccionariosTree();
                obtenerDepartamentos(departamentos);
                cargarTransaccionesXlocal(unidadesAntiguedad, codUnidadMedida,institucion,Constantes.COD_TRANSACCIONES_EXITOSAS);
                cargarTransaccionesXlocal(unidadesAntiguedad, codUnidadMedida, institucion, Constantes.COD_TRANSACCIONES_TOTALES);
                foreach (String d in departamentos)
                {
                    auxDepartamentos1.Add(d + " Dpto.");
                }

                foreach (String d in departamentos)
                {
                    auxProvincias1 = obtenerProvinciasXDepartamento(d, auxProvincias);
                    agregarHijosTree(d + " Dpto.", d, auxProvincias1, auxProvincias, tree, false);

                    foreach (String p in auxProvincias)
                    {
                        auxDistritos1 = obtenerDistritosXProvincia(d, p, auxDistritos);
                        agregarHijosTree(p + " Prov.", p, auxDistritos1, auxDistritos, tree, false);

                        foreach (String dist in auxDistritos)
                        {
                            distritoactual = dist;
                            auxLocales1 = obtenerLocalesXdistrito(locales, dist);
                            if (auxLocales1 != null && auxLocales1.Count() > 0)
                            {
                                antes = true;
                                agregarHijosTree(diccionarioDistritos[dist] + " Dist.", dist, auxLocales1, locales, tree, true);
                                despues = true;
                            }
                            locales = new List<String>();
                            antes = false;
                            despues = false;
                        }

                        auxDistritos = new List<String>();
                    }

                    auxProvincias = new List<String>();
                }
                //Agregar departamentos al tree

                agregarHijosTree("Peru", "Peru", auxDepartamentos1, departamentos, tree, false);
                TreeTransaccion elementoTree = new TreeTransaccion();
                elementoTree.vcHijo = "Peru";
                elementoTree.vcCodHijo = "Peru";
                elementoTree.vcPadre = null;
                elementoTree.vcCodPadre = null;
                tree.Add(elementoTree);
                return tree;
            }
            catch (Exception e)
            {
                string gg = e.Message;
                return null;
            }
        }

        public void agregarHijosTree(String padre, string codPadre, List<String> hijos, List<string> codHijos,List<TreeTransaccion> tree, bool ultimoNivel)
        {
            TreeTransaccion elementoTree;
            int i, totalTxn;
            try
            {
                for (i = 0; i < hijos.Count; i++)
                {
                    elementoTree = new TreeTransaccion();
                    elementoTree.vcHijo = hijos[i];
                    elementoTree.vcCodHijo = codHijos[i];
                    elementoTree.vcPadre = padre;
                    elementoTree.vcCodPadre = codPadre;
                    if (ultimoNivel)
                    {
                        if (diccionarioTxnsExitosasXLocal.ContainsKey(codHijos[i]))
                        {
                            elementoTree.inCantidadTransacciones = diccionarioTxnsExitosasXLocal[codHijos[i]];//obtenerCantTxnAleatorias();
                            //si por alguna razon no hay el local en el diccionario de te txn totales entonces
                            //el total de txns se obtiene del diccionario de exitosas
                            if (!diccionarioTxnsTotalesXLocal.ContainsKey(codHijos[i]))
                            {
                                totalTxn = elementoTree.inCantidadTransacciones;
                            }
                            else
                            {
                                totalTxn = diccionarioTxnsTotalesXLocal[codHijos[i]];
                            }
                            
                            if(totalTxn < 1){
                                elementoTree.inColor = -1;
                            }
                            else{
                                elementoTree.inColor = (int)((elementoTree.inCantidadTransacciones * Constantes.ESCALA_PORCENTAJE_TREE) / totalTxn - Constantes.ESCALA_NEGATIVO_TREE);
                            }
                        }
                        else { elementoTree.inCantidadTransacciones = 0; }
                        if (diccionarioDirsXLocal.ContainsKey(codHijos[i]))
                        {
                            elementoTree.inCantidadDIR = diccionarioDirsXLocal[codHijos[i]];//obtenerCantDirAleatorios();
                        }
                        else { elementoTree.inCantidadDIR = 1; }
                    }
                    tree.Add(elementoTree);
                }
            }
            catch(Exception e)
            {
                string gg = e.Message;
            }
        }

        //********************* INICIO METODOS QUE ALIMENTAN AL METODO obtenerConsolidadoTransacciones ********************

        private void agregarElementosTreeTxn(List<TreeTransaccion> auxiliarTree, List<TreeTransaccion> tree)
        {
            foreach (TreeTransaccion elementoTree in auxiliarTree)
            {
                tree.Add(elementoTree);
            }
        }

        private void obtenerDataSetTreeTxn(DataSet ds, List<TreeTransaccion> tree)
        {
            TreeTransaccion elementoTree;
            foreach(DataRow dr in ds.Tables[0].Rows){
                elementoTree = new TreeTransaccion();
                elementoTree.vcPadre = dr["vcPadre"].ToString();
                elementoTree.vcHijo = dr["vcHijo"].ToString();
                elementoTree.inCantidadTransacciones = Int32.Parse(dr["inCantidadTransacciones"].ToString());
                elementoTree.inCantidadDIR = Int32.Parse(dr["inCantidadDIR"].ToString());
                tree.Add(elementoTree);
            }
        }

        private List<TreeTransaccion> obtenerConsTreeStoredProc(DateTime? desde, DateTime? hasta, int rango)
        {
            List<SqlParameter> listaParametros = new List<SqlParameter>();
            DataSet ds = new DataSet();
            List<TreeTransaccion> tree = new List<TreeTransaccion>();
            
            SqlParameter param1 = new SqlParameter("@desde", SqlDbType.DateTime);
            SqlParameter param2 = new SqlParameter("@hasta", SqlDbType.DateTime);
            
            param1.Value = desde;
            param2.Value = hasta;
            listaParametros.Add(param1);
            listaParametros.Add(param2);
            
            dbSQL.ejecutarSelectProcedureDS(Utils.ProcedimientosAlmacenados.ConsolidadoTreeLocales, listaParametros, ds);
             
            obtenerDataSetTreeTxn(ds, tree);

            return tree;
        }

        //********************* FIN METODOS QUE ALIMENTAN AL METODO obtenerConsolidadoTransacciones ************************


                
        public List<ConsolidadoEstadoTransaccion> obtenerConsolidadoEstados(int? idTipoTxn, int? idCategoria, int nivel,
                                                                            int unidadesAntiguedad, int codigoTabla,
                                                                            string elementoHijoNivel, string elementoPadreNivel,
                                                                            int tipoChart, int institucion)
        {
            List<ConsolidadoGeneral> consolidado = new List<ConsolidadoGeneral>();
            List<ConsolidadoEstadoTransaccion> consolidadoEstados = new List<ConsolidadoEstadoTransaccion>();



            obtenerConsEstadosStoredProc(consolidadoEstados, nivel, idTipoTxn, elementoHijoNivel, elementoPadreNivel,
            unidadesAntiguedad, codigoTabla, idCategoria, tipoChart,institucion);
            

            return consolidadoEstados;
        }

        //************************* INICIO METODOS QUE ALIMENTAN AL METODO obtenerConsolidadoEstados *********************

        private void obtenerDataSetEstados(DataSet ds, List<ConsolidadoEstadoTransaccion> consolidado, int tipoChart,
                                        int codUnidadMedida)
        {
            ConsolidadoEstadoTransaccion elementoEstado;
            string stFecha;
            int i = 0;
            foreach (DataRow dr in ds.Tables[0].Rows)
            {
                elementoEstado = new ConsolidadoEstadoTransaccion();

                elementoEstado.idEstado = Int32.Parse(dr[i].ToString()); i++;
                elementoEstado.vcEstado = diccionarioEstados[elementoEstado.idEstado];
                if (tipoChart == Constantes.LINECHART)
                //if (tipoChart == Constantes.TABLECHART || tipoChart == Constantes.LINECHART)
                {
                    stFecha = dr[i].ToString();
                    if (codUnidadMedida == 1)
                    {
                        stFecha = (stFecha).Split(' ')[0]; i++;
                        elementoEstado.dtFecha = DateTime.ParseExact(stFecha, "dd/MM/yyyy", CultureInfo.InvariantCulture);
                    }
                    else if (codUnidadMedida == 2)
                    {
                        elementoEstado.vcSemana = stFecha; i++;
                    }
                    else if (codUnidadMedida == 3)
                    {
                        elementoEstado.vcMes = stFecha; i++;
                    }
                    else
                    {
                        elementoEstado.inAno = Int32.Parse(stFecha); i++;
                    }
                }
                
                elementoEstado.inCantidad = Int32.Parse(dr[i].ToString());
                consolidado.Add(elementoEstado);
                i = 0;
            }
        }

        //Obtencion del consulidado de estados mediante stored procedures.
        private void obtenerConsEstadosStoredProc(List<ConsolidadoEstadoTransaccion> consolidadoEstados, int nivel,
                                                        int? idTipoTransaccion,string elementoHijoNivel, 
                                                        string elementoPadreNivel, int? unidadesAntiguedad, 
                                                        int codUnidadMedida, int? idCategoria, int tipoChart,
                                                        int institucion)
        {
            List<SqlParameter> listaParametros = new List<SqlParameter>();
            DataSet ds = new DataSet();


            //modificar parametro de rango
            agregarParametrosGenerales(listaParametros, elementoHijoNivel, elementoPadreNivel, unidadesAntiguedad,
                                        codUnidadMedida,nivel);

            SqlParameter param1 = new SqlParameter("@idTransaccion", SqlDbType.Int);
            SqlParameter param2 = new SqlParameter("@idCategoria", SqlDbType.Int);
            SqlParameter param3 = new SqlParameter("@codInstitucion", SqlDbType.Int);

            if (idTipoTransaccion == null)
            {
                param1.Value = -1;
            }
            else
            {
                param1.Value = idTipoTransaccion;
            }
            
            if (idCategoria == null)
            {
                param2.Value = -1;
            }
            else
            {
                param2.Value = idCategoria;
            }

            param3.Value = institucion;

            listaParametros.Add(param1);
            listaParametros.Add(param2);
            listaParametros.Add(param3);

            //un solo proc de consolidado estados y dentro hace un where condicional, AGREGAR NIVEL como parametro
            if (tipoChart == Constantes.LINECHART)
            {
                dbSQL.ejecutarSelectProcedureDS(Utils.ProcedimientosAlmacenados.ConsolidadoEstadosTabla, listaParametros, ds);
            }
            else
            {
                dbSQL.ejecutarSelectProcedureDS(Utils.ProcedimientosAlmacenados.ConsolidadoEstados, listaParametros, ds);
            }
            obtenerDataSetEstados(ds, consolidadoEstados, tipoChart, codUnidadMedida);

        }
        //*********************** FIN METODOS QUE ALIMENTAN AL METODO obtenerConsolidadoEstados *************************



        public List<ConsolidadoTipoTransaccion> obtenerConsolidadoTipos(int? idEstado, int? idCategoria, int nivel, 
                                                                    int unidadesAntiguedad, int codigoTabla,
                                                                    string elementoHijoNivel, string elementoPadreNivel,
                                                                    int tipoChart, int institucion)
        {
            List<ConsolidadoGeneral> consolidado = new List<ConsolidadoGeneral>();
            List<ConsolidadoTipoTransaccion> consolidadoTipos = new List<ConsolidadoTipoTransaccion>();

            //para el caso que es tablas obtenemos 2 consolidados
            if (tipoChart == Constantes.TABLECHART)
            {
                obtenerConsTiposStoredProc(consolidadoTipos, nivel, idEstado, elementoHijoNivel, elementoPadreNivel,
                unidadesAntiguedad, idCategoria, codigoTabla, Constantes.PIECHART, institucion); //el consolidado normal
                if (idEstado == null)
                {
                    List<ConsolidadoTipoTransaccion> consolidadoTiposAux = new List<ConsolidadoTipoTransaccion>();
                    obtenerConsTiposStoredProc(consolidadoTiposAux, nivel, idEstado, elementoHijoNivel, elementoPadreNivel,
                    unidadesAntiguedad, idCategoria, codigoTabla, tipoChart, institucion);
                    int j, i;
                    for (i = 0; i < consolidadoTipos.Count(); i++)
                    {
                        for (j = 0; j < consolidadoTiposAux.Count(); j++)
                        {
                            if (consolidadoTipos[i].idTipo == consolidadoTiposAux[j].idTipo) { break; }
                        }
                        consolidadoTipos[i].inCantEstado1 = consolidadoTiposAux[j].inCantidad;
                        consolidadoTipos[i].inCantEstado2 = consolidadoTiposAux[j].inCantEstado2;
                        consolidadoTipos[i].inCantEstado3 = consolidadoTiposAux[j].inCantEstado3;
                        consolidadoTipos[i].inCantEstado4 = consolidadoTiposAux[j].inCantEstado4;
                    }
                }

            }
            else
            {
                obtenerConsTiposStoredProc(consolidadoTipos, nivel, idEstado, elementoHijoNivel, elementoPadreNivel,
                unidadesAntiguedad, idCategoria, codigoTabla, tipoChart, institucion);
            }
        
            return consolidadoTipos;
        }

        //********************** INICIO METODOS QUE ALIMENTAN AL METODO obtenerConsolidadoTipos **************************

        
        private void obtenerDataSetTiposCat(DataSet ds, List<ConsolidadoTipoTransaccion> consolidado, int? idCategoria,
                                            int nivel, string elementoHijoNivel,
                                            string elementoPadreNivel, int? unidadesAntiguedad, int codUnidadMedida,
                                            int tipoChart,int institucion, int? idEstado)
        {
            ConsolidadoTipoTransaccion elementoTipo;
            //bool tipoTxn = false;
            List<ConsolidadoEstadoTransaccion> consolidadoEstados = new List<ConsolidadoEstadoTransaccion>();
            TipoTransaccion tipo;
            int cantExitosas, cantTruncas,i;
            string stFecha;
            i = 0;
            foreach (DataRow dr in ds.Tables[0].Rows)
            {
                elementoTipo = new ConsolidadoTipoTransaccion();
                elementoTipo.idTipo = Int32.Parse(dr[i].ToString()); i++;

                if (tipoChart == Constantes.LINECHART)                
                {
                    stFecha = dr[i].ToString();
                    if (codUnidadMedida == 1)
                    {
                        stFecha = (stFecha).Split(' ')[0]; i++;
                        elementoTipo.dtFecha = DateTime.ParseExact(stFecha, "dd/MM/yyyy", CultureInfo.InvariantCulture);
                    }
                    else if (codUnidadMedida == 2)
                    {
                        elementoTipo.vcSemana = stFecha; i++;
                    }
                    else if (codUnidadMedida == 3)
                    {
                        elementoTipo.vcMes = stFecha; i++;
                    }
                    else
                    {
                        elementoTipo.inAno = Int32.Parse(stFecha); i++;
                    }
                }
                
                elementoTipo.inCantidad = Int32.Parse(dr[i].ToString()); i=0;
                consolidado.Add(elementoTipo);
                
            }
            foreach (ConsolidadoTipoTransaccion c in consolidado)
            {   
                if (idCategoria!=null)
                {
                    c.vcNombreTipoTransaccion = diccionarioTipos[c.idTipo];
                    if (tipoChart == Constantes.TABLECHART && idEstado == null)
                    {
                        consolidadoEstados = obtenerConsolidadoEstados(c.idTipo, null, nivel,
                                        (int)unidadesAntiguedad, codUnidadMedida, elementoHijoNivel, elementoPadreNivel,
                                        Constantes.PIECHART, institucion);
                    }
                }
                else
                {
                    if (tipoChart == Constantes.TABLECHART && idEstado == null)
                    {
                        consolidadoEstados = obtenerConsolidadoEstados(null, c.idTipo, nivel,
                                            (int)unidadesAntiguedad, codUnidadMedida, elementoHijoNivel, elementoPadreNivel,
                                            Constantes.PIECHART, institucion);
                    }
                    c.vcNombreTipoTransaccion = diccionarioCategorias[c.idTipo];
                }
                if (tipoChart == Constantes.TABLECHART && idEstado == null)
                {
                                        
                    c.inCantEstado4 = 0;
                    foreach (var k in consolidadoEstados)
                    {
                        if (diccionarioEstados[k.idEstado].Equals("Aprobada"))
                        {
                            c.inCantEstado2 = k.inCantidad;
                        }
                        else if (diccionarioEstados[k.idEstado].Equals("No Imprimio"))
                        {
                            c.inCantEstado3 = k.inCantidad;
                        }
                        else if (diccionarioEstados[k.idEstado].Equals("Por Enviar"))
                        {
                            c.inCantEstado4 += k.inCantidad;
                        }
                        else if (diccionarioEstados[k.idEstado].Equals("Time Out"))
                        {
                            c.inCantEstado4 += k.inCantidad;
                        }
                    }
                }

            }
        }

        private void obtenerConsTiposStoredProc(List<ConsolidadoTipoTransaccion> consolidadoTipos, int nivel,
                                                        int? idEstado, string elementoHijoNivel,
                                                        string elementoPadreNivel, int? unidadesAntiguedad, 
                                                        int? idCategoria, int codUnidadMedida, int tipoChart,
                                                        int institucion)
        {
            List<SqlParameter> listaParametros = new List<SqlParameter>();
            DataSet ds = new DataSet();

            //modificar parametro rango
            agregarParametrosGenerales(listaParametros, elementoHijoNivel, elementoPadreNivel,unidadesAntiguedad,
                                        codUnidadMedida, nivel);

            SqlParameter param1 = new SqlParameter("@idEstado", SqlDbType.Int);
            SqlParameter param2 = new SqlParameter("@idCategoria", SqlDbType.Int);
            SqlParameter param3 = new SqlParameter("@codInstitucion", SqlDbType.Int);

            if (idEstado == null)
            {
                param1.Value = -1;
            }
            else
            {
                param1.Value = idEstado;
            }
            if (idCategoria == null)
            {
                param2.Value = -1;
            }
            else
            {
                param2.Value = idCategoria;
            }

            param3.Value = institucion;

            listaParametros.Add(param1);
            listaParametros.Add(param2);
            listaParametros.Add(param3);

            if (tipoChart == Constantes.TABLECHART)
            {
                dbSQL.ejecutarSelectProcedureDS(Utils.ProcedimientosAlmacenados.ConsolidadoTiposTabla, listaParametros, ds);
            }
            else if (tipoChart == Constantes.LINECHART)
            {
                dbSQL.ejecutarSelectProcedureDS(Utils.ProcedimientosAlmacenados.ConsolidadoTiposLinea, listaParametros, ds);
            }
            else
            {
                dbSQL.ejecutarSelectProcedureDS(Utils.ProcedimientosAlmacenados.ConsolidadoTipos, listaParametros, ds);
            }
                    
            obtenerDataSetTiposCat(ds, consolidadoTipos,idCategoria,nivel,elementoHijoNivel,elementoPadreNivel,
                                unidadesAntiguedad,codUnidadMedida,tipoChart,institucion,idEstado);

        }

        //*********************** FIN METODOS QUE ALIMENTAN AL METODO obtenerConsolidadoTipos ***************************



        public List<ConsolidadoMontoTransaccion> obtenerConsolidadoMontos(int? idEstado, int? idCategoria, int? idTipo,
                                                                        string elementoHijoNivel, string elementoPadreNivel, 
                                                                        int nivel,int codigoTabla, int unidadesAntiguedad,
                                                                        int tipoChart, int institucion)
        {
            List<ConsolidadoGeneral> consolidado = new List<ConsolidadoGeneral>();
            List<ConsolidadoMontoTransaccion> consolidadoMontos = new List<ConsolidadoMontoTransaccion>();
            obtenerConsMontosStoredProc(consolidadoMontos,nivel,idEstado,elementoHijoNivel,idTipo,elementoPadreNivel,
                                        unidadesAntiguedad,codigoTabla,idCategoria, tipoChart,institucion);
                                   

            return consolidadoMontos;
        }

        private void obtenerDataSetMontos(DataSet ds, List<ConsolidadoMontoTransaccion> consolidado, int tipoChart,
                                        int nivel, int codUnidadMedida)
        {
            ConsolidadoMontoTransaccion elementoMonto;
            ConsolidadoAuxiliarMonto elementoAuxMonto;
            string stFecha;
            List<ConsolidadoAuxiliarMonto> listaAuxConsMonto = new List<ConsolidadoAuxiliarMonto>();
            //para manejar diferentes consolidados segun chart
            int i = 0;
            try
            {
                foreach (DataRow dr in ds.Tables[0].Rows)
                {
                    elementoAuxMonto = new ConsolidadoAuxiliarMonto();

                    elementoAuxMonto.vcNombreMovimiento = dr[i].ToString(); i++;

                    //para todos lo niveles excepto a nivel de DIR
                    if (tipoChart == Constantes.TABLECHART && nivel != 1)
                    {
                        elementoAuxMonto.idEstado = Int32.Parse(dr[i].ToString()); i++;
                        elementoAuxMonto.vcNombreEstadoTransaccion = diccionarioEstados[elementoAuxMonto.idEstado];
                    }
                    if (tipoChart == Constantes.TABLECHART && nivel == 1)
                    {
                        elementoAuxMonto.vcCodDir = dr[i].ToString(); i++;
                    }

                    
                    stFecha = dr[i].ToString();
                    if (codUnidadMedida == 1)
                    {
                        stFecha = (stFecha).Split(' ')[0]; i++;
                        elementoAuxMonto.stFecha = stFecha;
                    }
                    
                    else
                    {
                        elementoAuxMonto.stFecha = stFecha; i++;
                    }
                    //elementoAuxMonto.dtFecha = DateTime.ParseExact(stFecha, "dd/MM/yyyy", CultureInfo.InvariantCulture);
                    elementoAuxMonto.dbSumaMontos = Double.Parse(dr[i].ToString());
                    listaAuxConsMonto.Add(elementoAuxMonto);
                    i = 0;
                }


                //separar distintos consolidados
                var fechas = listaAuxConsMonto.AsQueryable().GroupBy(a => new { a.stFecha }).Select(a =>
                    new { fecha = a.Key.stFecha });

                var estados = listaAuxConsMonto.AsQueryable().GroupBy(a => new { a.idEstado }).Select(a =>
                    new { estado = a.Key.idEstado });

                double totAbonos, totTransf, totCargos;
                
                //Para el caso que sea el chart de tipo tabla entonces se debe acomodar el consolidado por estado de
                //transaccion
                if (tipoChart == Constantes.TABLECHART)
                {
                    //Cuando se encuentra a nivel de locales entonces se muestra los consolidados de montos x DIR.
                    if (nivel == Constantes.LOCALES)
                    {
                        var dirs = listaAuxConsMonto.AsQueryable().GroupBy(a => new { a.vcCodDir }).Select(a =>
                                    new { dir = a.Key.vcCodDir });
                        foreach (var f in fechas)
                        {
                            foreach (var d in dirs)
                            {
                                elementoMonto = new ConsolidadoMontoTransaccion();
                                elementoMonto.stFecha = f.fecha;
                                elementoMonto.vcCodDir = d.dir;
                                var subListaConsMonto = listaAuxConsMonto.AsQueryable().Where(a => a.stFecha == f.fecha &&
                                    a.vcCodDir == d.dir).ToList();
                                auxiliarDataSetMontos(subListaConsMonto, elementoMonto);

                                consolidado.Add(elementoMonto);
                            }
                        }
                    }
                    //para todos los demas niveles entonces se muestra los consolidados por estados.
                    else
                    {
                        foreach (var f in fechas)
                        {
                            totAbonos = 0; totCargos=0; totTransf=0;
                            foreach (var e in estados)
                            {
                                elementoMonto = new ConsolidadoMontoTransaccion();
                                elementoMonto.stFecha = f.fecha;
                                elementoMonto.vcNombreEstadoTransaccion = diccionarioEstados[e.estado];
                                var subListaConsMonto = listaAuxConsMonto.AsQueryable().Where(a => a.stFecha == f.fecha &&
                                    a.idEstado == e.estado).ToList();
                                auxiliarDataSetMontos(subListaConsMonto, elementoMonto);
                                totAbonos += elementoMonto.dbAbono;
                                totCargos += elementoMonto.dbCargo;
                                totTransf += elementoMonto.dbTransferencia;
                                consolidado.Add(elementoMonto);
                            }
                            elementoMonto = new ConsolidadoMontoTransaccion();
                            elementoMonto.stFecha = f.fecha;
                            elementoMonto.vcNombreEstadoTransaccion = "TODOS";
                            elementoMonto.dbAbono = totAbonos;
                            elementoMonto.dbCargo = totCargos;
                            elementoMonto.dbTransferencia = totTransf;
                            consolidado.Add(elementoMonto);
                        }
                    }
                }

                //para los demás tipos de chart no es necesario mostrar el consolidado por estado de transaccion
                else
                {
                    foreach (var f in fechas)
                    {
                        elementoMonto = new ConsolidadoMontoTransaccion();
                        elementoMonto.stFecha = f.fecha;

                        var subListaConsMonto = listaAuxConsMonto.AsQueryable().Where(a => a.stFecha == f.fecha).ToList();
                        auxiliarDataSetMontos(subListaConsMonto, elementoMonto);
                        consolidado.Add(elementoMonto);
                    }
                }
            }
            catch (Exception e)
            {
                string gg = e.Message;
            }
        }

        private void auxiliarDataSetMontos(List<ConsolidadoAuxiliarMonto> subListaConsMonto,
                                            ConsolidadoMontoTransaccion elementoMonto)
        {
            foreach (ConsolidadoAuxiliarMonto elemento in subListaConsMonto)
            {
                if ("Abono".Equals(elemento.vcNombreMovimiento))
                {
                    elementoMonto.dbAbono = elemento.dbSumaMontos;
                }
                else if ("Cargo".Equals(elemento.vcNombreMovimiento))
                {
                    elementoMonto.dbCargo = elemento.dbSumaMontos;
                }
                else if ("Transferencia".Equals(elemento.vcNombreMovimiento))
                {
                    elementoMonto.dbTransferencia = elemento.dbSumaMontos;
                }
            }
        }


        private void obtenerConsMontosStoredProc(List<ConsolidadoMontoTransaccion> consolidadoMontos, int nivel,
                                                        int? idEstado, string elementoHijoNivel, int? idTipo,
                                                        string elementoPadreNivel, int? unidadesAntiguedad,
                                                        int codUnidadMedida, int? idCategoria, int tipoChart,
                                                        int institucion)
        {
            List<SqlParameter> listaParametros = new List<SqlParameter>();
            DataSet ds = new DataSet();

            //modificar parametro rango
            agregarParametrosGenerales(listaParametros, elementoHijoNivel, elementoPadreNivel,unidadesAntiguedad,
                                        codUnidadMedida,nivel);

            SqlParameter param1 = new SqlParameter("@idEstado", SqlDbType.Int);
            SqlParameter param2 = new SqlParameter("@idCategoria", SqlDbType.Int);
            SqlParameter param3 = new SqlParameter("@idTransaccion", SqlDbType.Int);
            SqlParameter param4 = new SqlParameter("@codInstitucion", SqlDbType.Int);

            if (idEstado == null)
            {
                param1.Value = -1;
            }
            else
            {
                param1.Value = idEstado;
            }
            if (idCategoria == null)
            {
                param2.Value = -1;
            }
            else
            {
                param2.Value = idCategoria;
            }
            if (idTipo == null)
            {
                param3.Value = -1;
            }
            else
            {
                param3.Value = idTipo;
            }

            param4.Value = institucion;
            listaParametros.Add(param1);
            listaParametros.Add(param2);
            listaParametros.Add(param3);
            listaParametros.Add(param4);
            //Cuando se envía una peticion para obtener los consolidados para el chart de tipo tabla
            //entonces debe de obtenerse los consolidados de montos por estados de infraccion
            if (tipoChart == Constantes.TABLECHART && nivel != 1)
            {
                dbSQL.ejecutarSelectProcedureDS(Utils.ProcedimientosAlmacenados.ConsolidadoMontosTabla, listaParametros, ds);
            }
            
            //Caso contrario debe obtenerse los consolidados de montos generales
            else
            {
                dbSQL.ejecutarSelectProcedureDS(Utils.ProcedimientosAlmacenados.ConsolidadoMontos, listaParametros, ds);
            }
            obtenerDataSetMontos(ds, consolidadoMontos, tipoChart, nivel, codUnidadMedida);
            //obtenerDataSetTiposCat(ds, consolidadoTipos);

        }


        //*********************************** Inicio de Metodos GENERALES ************************************

        public void agregarParametrosGenerales(List<SqlParameter> listaParametros, string elementoHijoNivel,
                                        string elementoPadreNivel, int? unidadesAntiguedad, int codUnidadMedida,
                                        int nivel)
            
        {
            SqlParameter param1 = new SqlParameter("@unidadesAntiguedad", SqlDbType.Int);
            SqlParameter param2 = new SqlParameter("@elementoHijo", SqlDbType.VarChar, 100);
            SqlParameter param3 = new SqlParameter("@elementoPadre", SqlDbType.VarChar, 100);
            SqlParameter param4 = new SqlParameter("@codUnidadMedida", SqlDbType.Int);
            SqlParameter param5 = new SqlParameter("@nivel", SqlDbType.Int);

            param1.Value = unidadesAntiguedad;
            param4.Value = codUnidadMedida;
            param5.Value = nivel;

            if (elementoHijoNivel == null || Constantes.CADENA_VACIA.Equals(elementoHijoNivel))
            {
                param2.Value = Constantes.CADENA_VACIA;
            }
            else
            {
                param2.Value = elementoHijoNivel;
            }
            if (elementoPadreNivel == null || Constantes.CADENA_VACIA.Equals(elementoPadreNivel))
            {
                param3.Value = Constantes.CADENA_VACIA;
            }
            else
            {
                param3.Value = elementoPadreNivel;
            }

            listaParametros.Add(param1);
            listaParametros.Add(param2);
            listaParametros.Add(param3);
            listaParametros.Add(param4);
            listaParametros.Add(param5);
        }

        
        //*********************************** Fin de Metodos GENERALES ************************************


        public string obtenerCantTxnsTree(List<TreeTransaccion> consolidado)
        {
            
            return null;
        }

        public string obtenerCantTxnsConsolidadoTipos(List<ConsolidadoTipoTransaccion> consolidado)
        {
            int totalTxns= 0;
            foreach (ConsolidadoTipoTransaccion c in consolidado)
            {
                totalTxns += c.inCantidad;
            }
            return totalTxns.ToString();
        }

        public string obtenerCantTxnsConsolidadoEstados(List<ConsolidadoEstadoTransaccion> consolidado)
        {
            int totalTxns = 0;
            foreach (ConsolidadoEstadoTransaccion c in consolidado)
            {
                totalTxns += c.inCantidad;
            }
            return totalTxns.ToString();
        }

        public string obtenerCantTxnsConsolidadoMontos()
        {
            return null;
        }

    }


}